﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;

namespace SimpleIR
{
	/// <summary>
	/// This class represents any allocation operation (classes, arrays, struct initialization).
	/// </summary>
	public sealed class IRAllocationOp : IRByteCode
	{
		/// <summary>
		/// The type of location we want to allocate.
		/// </summary>
		private readonly IRType m_alloctype;

		/// <summary>
		/// The constructor we want to invoke (null if we are just allocating raw memory).
		/// </summary>
		private readonly IRInvokeIdentity m_consinv;

		/// <summary>
		/// True if this is an array allocation.
		/// </summary>
		public readonly bool IsArrayAlloc;

		/// <summary>
		/// For an allocation with a constructor call.
		/// </summary>
		public IRAllocationOp(IRInvokeIdentity cinvoke, IRSourceLocation sloc)
			: base(OpCode.Op.AllocCons, sloc)
		{
			this.m_alloctype = cinvoke.DefInClass;
			this.m_consinv = cinvoke;
			this.IsArrayAlloc = false;
		}

		/// <summary>
		/// For an allocation of an array without a constructor.
		/// </summary>
		public IRAllocationOp(IRArrayType arrayty, IRSourceLocation sloc)
			: base(OpCode.Op.AllocCons, sloc)
		{
			this.m_alloctype = arrayty;
			this.m_consinv = null;
			this.IsArrayAlloc = true;
		}

		public override String ToString()
		{
			if(this.IsArrayAlloc)
				return "new " + this.m_alloctype.ToString() + "[]";
			else
				return "new " + this.m_consinv.DefInClass.ToString() + " using " + this.m_consinv.ToString();
		}

		/// <summary>
		/// Return the type we are allocating.
		/// </summary>
		public IRType AllocType
		{ get { return this.m_alloctype; } }

		/// <summary>
		/// Return the identity of the constructor that is being invoked.
		/// </summary>
		public IRInvokeIdentity ConsIdentity
		{ get { return this.m_consinv; } }
	}
}
